﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "UsbPacket.h"
#include "../platform/Securec/securec.h"
#include "SecureLink/Channel.h"
using namespace UsbPacketClass;

UsbPacket::UsbPacket()
    : dataSize(0),
      data(nullptr),
      buffer(nullptr),
      bufferSize(0),
      tlvData(nullptr),
      tlvDataSize(0),
      payloadBuffer(nullptr),
      payloadBufferSize(0),
      readPayloadBuffer(nullptr),
      readPayloadBufferSize(0),
      checkCrc(0)
{
    tlv.clear();
}

UsbPacket::~UsbPacket()
{
    for (int i = 0; i < tlv.size(); i++) {
        if (tlv[i].data != nullptr) {
            delete [] tlv[i].data;
            tlv[i].data = nullptr;
        }
    }
    if (payloadBuffer != nullptr) {
        delete[] payloadBuffer;
        payloadBuffer = nullptr;
    }
    if (buffer != nullptr) {
        delete []buffer;
        buffer = nullptr;
    }
    if (data != nullptr) {
        delete []data;
        data = nullptr;
    }
}

PBYTE UsbPacket::GetBuffer()
{
    if (buffer != nullptr) {
        delete[] buffer;
        buffer = nullptr;
    }
    if (dataSize + sizeof(SleFrameHeader) > SEND_BUFFER_SIZE) {
        return nullptr;
    }
    buffer = new uint8_t[SEND_BUFFER_SIZE]();
    if (buffer == nullptr) {
        return nullptr;
    }
    errno_t errMemset = memset_s(buffer, SEND_BUFFER_SIZE, 0, SEND_BUFFER_SIZE);
    if (errMemset != EOK) {
        return nullptr;
    }
    bufferSize = SEND_BUFFER_SIZE;
    SleFrameHeader sleFrameHeader;
    errno_t errMemcpy = memcpy_s(buffer, sizeof (SleFrameHeader), &sleFrameHeader, sizeof (SleFrameHeader));
    if (errMemcpy != EOK) {
        return nullptr;
    }
    errMemcpy = memcpy_s(buffer + sizeof (SleFrameHeader), dataSize, data, dataSize);
    if (errMemcpy != EOK) {
        return nullptr;
    }
    unsigned short crc16 = ChannelClass::Channel::SopCrc16(buffer, sizeof (SleFrameHeader) + dataSize);
    errMemcpy = memcpy_s(buffer + sizeof (SleFrameHeader) + dataSize, CRC_SIZE, &crc16, CRC_SIZE);
    if (errMemcpy != EOK) {
        return nullptr;
    }

    return buffer;
}

PBYTE UsbPacket::GetBuffer(int total, int offset)
{
    if (buffer != nullptr) {
        delete[] buffer;
        buffer = nullptr;
    }
    if (dataSize + sizeof(SleFrameHeader) + CRC_SIZE > SEND_BUFFER_SIZE) {
        return nullptr;
    }
    buffer = new uint8_t[SEND_BUFFER_SIZE]();
    if (buffer == nullptr) {
        return nullptr;
    }
    errno_t errMemset = memset_s(buffer, SEND_BUFFER_SIZE, 0, SEND_BUFFER_SIZE);
    if (errMemset != EOK) {
        return nullptr;
    }
    bufferSize = SEND_BUFFER_SIZE;
    SleFrameHeader sleFrameHeader;
    sleFrameHeader.totalFrame = total;
    sleFrameHeader.frameSeq = offset;
    errno_t errMemcpy = memcpy_s(buffer, sizeof (SleFrameHeader), &sleFrameHeader, sizeof (SleFrameHeader));
    if (errMemcpy != EOK) {
        return nullptr;
    }
    errMemcpy = memcpy_s(buffer + sizeof (SleFrameHeader), dataSize, data, dataSize);
    if (errMemcpy != EOK) {
        return nullptr;
    }
    unsigned short crc16 = ChannelClass::Channel::SopCrc16(buffer, sizeof (SleFrameHeader) + dataSize);
    errMemcpy = memcpy_s(buffer + sizeof (SleFrameHeader) + dataSize, CRC_SIZE, &crc16, CRC_SIZE);
    if (errMemcpy != EOK) {
        return nullptr;
    }

    return buffer;
}

PBYTE UsbPacket::GetData()
{
    return this->data;
};

uint16_t UsbPacket::GetDataSize() const
{
    return this->dataSize;
};

uint32_t UsbPacket::GetBufferSize() const
{
    return bufferSize;
}

BOOL UsbPacket::CheckCrc() const
{
    return TRUE;
};

void UsbPacket::Init(PBYTE input, uint32_t inputLen)
{
    readPayloadBufferSize = 0;
    if (inputLen < sizeof (SleFrameHeader) + sizeof (PayloadBuffer)) {
        return;
    }
    SleFrameHeader *p = reinterpret_cast<SleFrameHeader *>(input);
    if (p == nullptr) {
        return;
    }
    startFlag = p->flag;
    if (startFlag != 0x1f) {
        return;
    }
    readPayloadBuffer = reinterpret_cast<PayloadBuffer *>(input + sizeof (SleFrameHeader));
    if (inputLen - sizeof (SleFrameHeader) - sizeof (PayloadBuffer) < readPayloadBuffer->bodyLen + CRC_SIZE) {
        return;
    }
    readPayloadBufferSize += sizeof (SleFrameHeader) + sizeof (PayloadBuffer) + readPayloadBuffer->bodyLen + CRC_SIZE;
    int crcOffset = sizeof (SleFrameHeader) + readPayloadBuffer->bodyLen;
    errno_t errMemcpy = memcpy_s(&crc, sizeof (uint16_t), input + crcOffset, sizeof (uint16_t));
    if (errMemcpy != EOK) {
        return;
    }
    checkCrc = ChannelClass::Channel::SopCrc16(input, crcOffset);
    SetData(readPayloadBuffer->body, readPayloadBuffer->bodyLen);
}

PayloadBuffer *UsbPacket::GetReadPayloadBuffer()
{
    return readPayloadBuffer;
}

uint32_t UsbPacket::GerReadPayloadBufferSize() const
{
    return readPayloadBufferSize;
}

void UsbPacket::SetData(const PBYTE pcData, uint16_t u16DataSize)
{
    if (this->data) {
        delete[] this->data;
        this->data = nullptr;
    }
    this->dataSize = u16DataSize;
    if (pcData == nullptr) {
        return;
    }
    if (this->dataSize == 0 || this->dataSize > 0xFFFF) {
        return;
    }
    this->data = new BYTE[this->dataSize]();
    if (this->data != nullptr) {
        errno_t errMemcpy = memset_s(this->data, this->dataSize, 0, this->dataSize);
        if (errMemcpy != EOK) {
            return;
        }
        errMemcpy = memcpy_s(this->data, dataSize, pcData, dataSize);
        if (errMemcpy != EOK) {
            return;
        }
    }
};

PBYTE UsbPacket::GetPayloadPack(const uint8_t serviceId, const uint8_t commandId)
{
    if (payloadBuffer != nullptr) {
        delete[] payloadBuffer;
        payloadBuffer = nullptr;
    }
    payloadBufferSize = 0;
    payloadBufferSize += sizeof(uint8_t);
    payloadBufferSize += sizeof(uint8_t);
    payloadBufferSize += sizeof(uint16_t);
    if (tlvDataSize != 0 && tlvData != nullptr) {
        payloadBufferSize += tlvDataSize;
    }
    payloadBuffer = new uint8_t[payloadBufferSize]();
    if (payloadBuffer == nullptr) {
        return nullptr;
    }
    int payloadSize = 0;
    errno_t errMemset = memset_s(payloadBuffer, payloadBufferSize, 0, payloadBufferSize);
    if (errMemset != EOK) {
        return nullptr;
    }
    errno_t errMemcpy = memcpy_s(payloadBuffer, sizeof(uint8_t), &serviceId, sizeof(uint8_t));
    if (errMemcpy != EOK) {
        return nullptr;
    }
    payloadSize += sizeof(uint8_t);
    errMemcpy = memcpy_s(payloadBuffer + payloadSize, sizeof(uint8_t), &commandId, sizeof(uint8_t));
    if (errMemcpy != EOK) {
        return nullptr;
    }
    payloadSize += sizeof(uint8_t);
    errMemcpy = memcpy_s(payloadBuffer + payloadSize, sizeof(uint16_t), &tlvDataSize, sizeof(uint16_t));
    if (errMemcpy != EOK) {
        return nullptr;
    }
    payloadSize += sizeof(uint16_t);
    if (tlvDataSize != 0 && tlvData != nullptr) {
        errMemcpy = memcpy_s(payloadBuffer + payloadSize, tlvDataSize, tlvData, tlvDataSize);
        if (errMemcpy != EOK) {
            return nullptr;
        }
        payloadSize += tlvDataSize;
        delete []tlvData;
        tlvData = nullptr;
        tlvDataSize = 0;
    }
    return payloadBuffer;
}

void UsbPacket::SetTlv(const uint8_t type, const PBYTE pcData, uint16_t u16DataSize)
{
    if (tlvData == nullptr) {
        tlvData = new uint8_t[2048]();
        if (tlvData == nullptr) {
            return;
        }
        errno_t errMemcpy = memset_s(tlvData, 2048, 0, 2048);
        if (errMemcpy != EOK) {
            return;
        }
        tlvDataSize = 0;
    }
    errno_t errMemcpy = memcpy_s(tlvData + tlvDataSize, sizeof(uint8_t), &type, sizeof(uint8_t));
    if (errMemcpy != EOK) {
        return;
    }
    tlvDataSize += sizeof(uint8_t);
    errMemcpy = memcpy_s(tlvData + tlvDataSize, sizeof(uint16_t), &u16DataSize, sizeof(uint16_t));
    if (errMemcpy != EOK) {
        return;
    }
    tlvDataSize += sizeof(uint16_t);
    errMemcpy = memcpy_s(tlvData + tlvDataSize, u16DataSize, pcData, u16DataSize);
    if (errMemcpy != EOK) {
        return;
    }
    tlvDataSize += u16DataSize;
}

uint32_t UsbPacket::GetPayloadBufferSize() const
{
    return payloadBufferSize;
}

QVector<Tlv> UsbPacket::GetTlvVec(PBYTE tlvByte, uint16_t tlvByteSize)
{
    for (int i = 0; i < tlv.size(); i++) {
        if (tlv[i].data != nullptr) {
            delete [] tlv[i].data;
            tlv[i].data = nullptr;
        }
    }
    tlv.clear();
    uint16_t offset = 0;
    while (offset < tlvByteSize) {
        Tlv tlvBuffer;
        errno_t errMemcpy = memcpy_s(&(tlvBuffer.type), sizeof (uint8_t), tlvByte + offset, sizeof (uint8_t));
        if (errMemcpy != EOK) {
            break;
        }
        offset += sizeof (uint8_t);
        errMemcpy = memcpy_s(&(tlvBuffer.lenth), sizeof (uint16_t), tlvByte + offset, sizeof (uint16_t));
        if (errMemcpy != EOK) {
            break;
        }
        offset += sizeof (uint16_t);
        tlvBuffer.data = new BYTE[tlvBuffer.lenth]();
        if (tlvBuffer.data != nullptr) {
            errMemcpy = memcpy_s(tlvBuffer.data, tlvBuffer.lenth, tlvByte + offset, tlvBuffer.lenth);
            if (errMemcpy != EOK) {
                break;
            }
            offset += tlvBuffer.lenth;
            tlv.push_back(tlvBuffer);
        }
    }
    return tlv;
}

